#include <gl\glew.h>
#include <IL\il.h>
#include <IL\ilu.h>
#include <IL\ilut.h>
#include "GLTexture.h"
#include "..\..\Math\Colorb.h"

#include <wx\bitmap.h>

GLTexture::~GLTexture()
{
	//if (_id != 0)
	//	throw std::exception("Texture deleted whilst still being loaded");
}

void GLTexture::DeleteIfLoaded()
{
	if (_id != 0)
		Delete();
}

void GLTexture::EnsureIL()
{
	static bool _callbackSet = false;
	
	if (!_callbackSet)
	{
		ilInit();
		_callbackSet = true;
	}
}

void GLTexture::CreateImage()
{
	glGenTextures(1, &_id);
}

void GLTexture::BlitData(const int &bpp, const int &format, const byte *data)
{
	glBindTexture(GL_TEXTURE_2D, _id);

	glTexImage2D(GL_TEXTURE_2D, 0, bpp, _width, _height, 0, format, GL_UNSIGNED_BYTE, data);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBindTexture(GL_TEXTURE_2D, 0);
}

void GLTexture::Load(const byte *data, const int &width, const int &height)
{
	DeleteIfLoaded();
	CreateImage();
	
	_width = width;
	_height = height;
	_scale = 1;

	BlitData(4, GL_RGBA, data);
}

void GLTexture::Load(wxInputStream &stream)
{
	EnsureIL();
	DeleteIfLoaded();
	CreateImage();

	size_t cnt = stream.GetLength();
	byte *data = new byte[cnt];

	stream.Read(data, cnt);

	auto img = ilGenImage();
	ilBindImage(img);
	ilLoadL(IL_PNG, data, cnt);

	ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);

	_width = ilGetInteger(IL_IMAGE_WIDTH);
	_height = ilGetInteger(IL_IMAGE_HEIGHT);
	_scale = 1;

	BlitData(ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_FORMAT), ilGetData());

	ilBindImage(0);
	ilDeleteImage(img);
	delete[] data;
}

void GLTexture::Copy(const ITexture *texture)
{
	DeleteIfLoaded();

	const GLTexture *gl = static_cast<const GLTexture*>(texture);
	_id = gl->GetID();
	_width = gl->GetWidth();
	_height = gl->GetHeight();
	_scale = gl->GetScale();
}

void GLTexture::Delete()
{
	if (_id == 0)
		throw std::exception("GLTexture::Delete called with no ID");
	
	glDeleteTextures(1, &_id);
	_id = 0;
	_width = _height = _scale = -1;
}

void GLTexture::BlitData(Colorb *ptr)
{
	glBindTexture(GL_TEXTURE_2D, _id);
	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
	glBindTexture(GL_TEXTURE_2D, 0);
}